using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Utils.Coroutine
{
    public static class WaitExtender
    {
        /// <summary>
        /// 等待指定秒数后执行下一个动作。
        /// </summary>
        /// <param name="actionQueue">动作队列</param>
        /// <param name="seconds">等待的秒数</param>
        /// <returns>动作队列</returns>
        public static ActionQueue AppendWaitSeconds(this ActionQueue actionQueue, float seconds)
        {
            actionQueue.Append(WaitSecondsCondition(seconds));
            return actionQueue;
        }

        private static IEnumerator WaitSecondsCondition(float seconds)
        {
            yield return new WaitForSeconds(seconds);
        }

        /// <summary>
        /// 等待当前帧结束。
        /// </summary>
        /// <param name="actionQueue">动作队列</param>
        /// <returns>动作队列</returns>
        public static ActionQueue AppendWaitEndOfFrame(this ActionQueue actionQueue)
        {
            actionQueue.Append(WaitEndOfFrameCondition());
            return actionQueue;
        }

        private static IEnumerator WaitEndOfFrameCondition()
        {
            yield return new WaitForEndOfFrame();
        }

        /// <summary>
        /// 等待指定帧数。
        /// </summary>
        /// <param name="actionQueue">动作队列</param>
        /// <param name="frameCount">等待的帧数</param>
        /// <returns>动作队列</returns>
        public static ActionQueue AppendWaitFrames(this ActionQueue actionQueue, int frameCount)
        {
            actionQueue.Append(WaitFramesCondition(frameCount));
            return actionQueue;
        }

        private static IEnumerator WaitFramesCondition(int frameCount)
        {
            for (int i = 0; i < frameCount; i++)
                yield return null;
        }

        /// <summary>
        /// 等待下一帧。
        /// </summary>
        /// <param name="actionQueue">动作队列</param>
        /// <returns>动作队列</returns>
        public static ActionQueue AppendWaitNextFrame(this ActionQueue actionQueue)
        {
            actionQueue.Append(WaitNextFrameCondition());
            return actionQueue;
        }

        private static IEnumerator WaitNextFrameCondition()
        {
            yield return null;
        }
        
        /// <summary>
        /// 等待指定条件为true后执行回调函数。
        /// </summary>
        /// <param name="actionQueue">动作队列</param>
        /// <param name="condition">条件函数，返回布尔值</param>
        /// <returns>动作队列</returns>
        public static ActionQueue AppendWaitUntil(this ActionQueue actionQueue, Func<bool> condition)
        {
            actionQueue.Append(WaitUntilCondition(condition));
            return actionQueue;
        }

        private static IEnumerator WaitUntilCondition(Func<bool> condition)
        {
            yield return new WaitUntil(condition);
        }
    }
}
